<template>
  <el-dialog
    v-model="state.dialogVisible"
    :append-to-body="true"
    :before-close="close"
    :close-on-click-modal="true"
    :close-on-press-escape="true"
    :destroy-on-close="true"
    fullscreen
    :modal="model"
    :title="state.dialogTitle"
    :width="width"
  >
    <el-form ref="formRef" label-width="100px" :model="state.formData" :rules="state.formRules">
      <el-row :gutter="10">
        <el-col :span="8">
          <el-form-item label="所属分类:" prop="tableTypeCode">
            <el-cascader
              v-model="state.formData.tableTypeId"
              clearable
              :collapse-tags="true"
              :options="cascaderOptions.dataList"
              placeholder="请选择所属分类"
              :props="cascaderOptions.props"
              :show-all-levels="false"
              style="width: 100%"
              @change="handleTableTypeChange"
            />
          </el-form-item>
        </el-col>
        <el-col :span="8">
          <el-form-item label="数据源:" prop="dataSourceCode">
            <el-select
              v-for="item in state.dataSourceOptions"
              :key="item.dataSourceId"
              v-model="state.formData.dataSourceCode"
              :disabled="!state.operationAdd"
            >
              <el-option
                :key="item.dataSourceId"
                :label="item.dataSourceName"
                :value="item.dataSourceCode"
              />
            </el-select>
          </el-form-item>
        </el-col>
        <el-col :span="8">
          <el-form-item label="表状态:">
            <el-switch
              v-model="state.formData.createdTable"
              active-text="已创建"
              disabled
              inactive-text="未创建"
            />
          </el-form-item>
        </el-col>

        <el-col :span="8">
          <el-form-item label="数据库表名:" prop="tableShortName">
            <el-input
              v-model="state.formData.tableShortName"
              :maxlength="32"
              show-word-limit
              type="text"
              @change="handleTableNameChange"
              :disabled="!state.operationAdd"
            >
              <template #prepend>bus_</template>
            </el-input>
          </el-form-item>
        </el-col>
        <el-col :span="8">
          <el-form-item label="别名:" prop="tableKey">
            <el-input
              v-model="state.formData.tableKey"
              :maxlength="32"
              show-word-limit
              type="text"
            />
          </el-form-item>
        </el-col>
        <el-col :span="8">
          <el-form-item label="中文名:" prop="tableComment">
            <el-input
              v-model="state.formData.tableComment"
              :maxlength="256"
              show-word-limit
              type="text"
            />
          </el-form-item>
        </el-col>
      </el-row>
    </el-form>
    <el-row :gutter="0">
      <el-col :span="24">
        <el-button icon="circle-plus" type="primary" @click="handleAddColumn">添加字段</el-button>
      </el-col>
    </el-row>
    <el-form ref="tableFormRef" class="form-table" inline-message :model="state.tableForm">
      <el-table
        ref="tableRef"
        v-loading="state.tableForm.listLoading"
        border
        :data="state.tableForm.list"
        :height="state.tableForm.height"
        stripe
      >
        <el-table-column align="center" label="字段名" prop="columnName" show-overflow-tooltip>
          <template #default="{ row, column, $index }">
            <el-form-item
              :prop="'list[' + $index + '].' + column.property"
              :rules="state.tableForm.rules.columnName"
            >
              <el-input
                v-model="row.columnName"
                @input="value => handleInputChange(value, $index, column.property)"
              />
            </el-form-item>
          </template>
        </el-table-column>
        <el-table-column align="center" label="属性名" prop="columnKey" show-overflow-tooltip>
          <template #default="{ row, column, $index }">
            <el-form-item
              :prop="'list[' + $index + '].' + column.property"
              :rules="state.tableForm.rules.columnKey"
            >
              <el-input v-model="row.columnKey" disabled />
            </el-form-item>
          </template>
        </el-table-column>
        <el-table-column align="center" label="中文注释" prop="columnComment" show-overflow-tooltip>
          <template #default="{ row, column, $index }">
            <el-form-item
              :prop="'list[' + $index + '].' + column.property"
              :rules="state.tableForm.rules.columnComment"
            >
              <el-input
                v-model="row.columnComment"
                @input="value => handleInputChange(value, $index, column.property)"
              />
            </el-form-item>
          </template>
        </el-table-column>

        <el-table-column align="center" label="是否可空" prop="nullable" width="100">
          <template #default="{ row, column, $index }">
            <el-switch
              v-model="row.nullable"
              :disabled="row.primaryKey"
              @change="val => handleInputChange(val, $index, column.property)"
            />
          </template>
        </el-table-column>
        <el-table-column align="center" label="数据类型" prop="dataType">
          <template #default="{ row, column, $index }">
            <el-form-item
              :prop="'list[' + $index + '].' + column.property"
              :rules="state.tableForm.rules.dataType"
            >
              <el-select
                :key="$index"
                v-model="row.dataType"
                :disabled="row.primaryKey"
                @change="val => handleSelectChange(val, $index, column.property)"
              >
                <el-option
                  v-for="item in state.dataTypeOptions"
                  :key="$index + '_' + item.dataType"
                  :label="item.dataTypeText"
                  :value="item.dataType"
                />
              </el-select>
            </el-form-item>
          </template>
        </el-table-column>
        <el-table-column align="center" label="属性长度" prop="dataLength" width="160">
          <template #default="{ row, column, $index }">
            <el-row :gutter="0">
              <el-col :span="12">
                <el-form-item
                  :prop="'list[' + $index + '].' + column.property"
                  :rules="state.tableForm.rules.dataLength"
                >
                  <el-input
                    :disabled="row.primaryKey"
                    :max="2000"
                    :min="4"
                    v-model="row.dataLength"
                    style="width: 100%"
                    type="number"
                    @input="value => handleInputChange(value, $index, column.property)"
                  />
                </el-form-item>
              </el-col>
              <el-col v-show="row.dataType === 'number'" :span="12">
                <el-form-item
                  :prop="'list[' + $index + '].' + 'dataPrecision'"
                  :rules="state.tableForm.rules.dataPrecision"
                  v-if="row.dataType === 'number'"
                >
                  <el-input
                    :disabled="row.primaryKey"
                    :max="8"
                    :min="0"
                    v-model="row.dataPrecision"
                    style="width: 100%"
                    type="number"
                    @input="value => handleInputChange(value, $index, 'dataPrecision')"
                  />
                </el-form-item>
              </el-col>
            </el-row>
          </template>
        </el-table-column>
        <el-table-column align="center" label="默认值" prop="defaultValue" show-overflow-tooltip>
          <template #default="{ row, column, $index }">
            <el-form-item
              :prop="'list[' + $index + '].' + column.property"
              :rules="state.tableForm.rules.defaultValue"
            >
              <el-input
                v-if="!row.primaryKey && row.renderType !== 'Hidden'"
                :model-value="row.defaultValue"
                @input="value => handleInputChange(value, $index, column.property)"
              />
            </el-form-item>
          </template>
        </el-table-column>
        <el-table-column align="center" label="渲染组件" prop="renderType">
          <template #default="{ row, column, $index }">
            <el-form-item
              :prop="'list[' + $index + '].' + column.property"
              :rules="state.tableForm.rules.renderType"
            >
              <el-select
                :key="$index"
                v-model="row.renderType"
                :disabled="row.primaryKey || row.renderType === 'Hidden'"
                filterable
                @change="val => handleSelectChange(val, $index, column.property)"
              >
                <el-option
                  v-for="item in state.renderTypeOptions"
                  :key="$index + '_' + item.value"
                  :label="item.label"
                  :value="item.value"
                />
              </el-select>
            </el-form-item>
          </template>
        </el-table-column>
        <el-table-column align="center" label="渲染数据" prop="convertConfig" width="220">
          <template #default="{ row, column, $index }">
            <el-form-item :prop="'list[' + $index + '].' + column.property">
              <span
                v-if="
                  row.convertConfig &&
                  Object.prototype.hasOwnProperty.call(row.convertConfig, 'type')
                "
              >
                <span v-if="row.convertConfig.type === 'UserName'">人员姓名</span>
                <span v-else-if="row.convertConfig.type === 'DeptName'">部门名称</span>
                <span v-else-if="row.convertConfig.targetTableName"
                  >{{ row.convertConfig.targetTableName }}-{{
                    row.convertConfig.targetColumnComment
                  }}</span
                >
              </span>
              <el-button
                type="primary"
                size="small"
                icon="Plus"
                circle
                @click="handleConverterAdd(row)"
              />
              <el-button
                type="danger"
                size="small"
                icon="Remove"
                circle
                @click="handleConverterRemove(row)"
              />
            </el-form-item>
          </template>
        </el-table-column>
        <el-table-column align="center" border fixed="right" label="操作" width="120">
          <template #default="{ row, $index }">
            <div v-if="row.primaryKey">
              <el-tag type="danger">主键字段</el-tag>
            </div>
            <div v-else style="width: 100%">
              <el-row style="width: 100%">
                <el-col
                  v-show="
                    $index > 0 &&
                    row.columnName !== 'flow_inst_id' &&
                    row.columnName !== 'order_inst_id'
                  "
                  :span="8"
                >
                  <el-button
                    type="danger"
                    icon="CloseBold"
                    size="small"
                    circle
                    @click="handleDeleteColumn($index)"
                  ></el-button>
                </el-col>
                <el-col v-show="$index > 1" :span="8">
                  <el-button
                    type="primary"
                    icon="Top"
                    size="small"
                    circle
                    @click="swapUp($index)"
                  ></el-button>
                </el-col>
                <el-col v-show="$index < state.tableForm.list.length - 1" :span="8">
                  <el-button
                    type="info"
                    icon="Bottom"
                    size="small"
                    circle
                    @click="swapDown($index)"
                  ></el-button>
                </el-col>
              </el-row>
            </div>
          </template>
        </el-table-column>
      </el-table>
    </el-form>
    <template #footer>
      <el-button icon="circle-close" type="warning" @click="close"> 取消 </el-button>
      <el-button :disabled="state.readonly" icon="circle-check" type="primary" @click="save">
        确定
      </el-button>
    </template>
    <CommonDialog
      v-model="converterShow"
      title="渲染数据配置"
      @cancel="converterShow = false"
      @closed="converterShow = false"
      @ok="handleConverterConfirm"
    >
      <Converter ref="converterRef"></Converter>
    </CommonDialog>
  </el-dialog>
</template>

<script setup name="DefTableEdit" lang="ts">
import { useMessage } from "@/hooks/message";
import { cloneObject, filterTreeNode } from "@/utils/common";
import { querySystemTreeNode } from "@/api/admin/system/systemtree/";
import { addTable, updateTable } from "@/api/def/table";
import { queryBusColumnList } from "@/api/def/column";
import { getTableHeight, toCamelCase } from "@/utils/util";
import { useCascader } from "@/hooks/cascader";
import {
  DefTableRules,
  DefaultColumnList,
  DefColumnRules,
  dataSourceOptions,
  dataTypeOptions,
  renderTypeOptions
} from "@/views/def/table/DefColumn";
import type { BasicCascaderProps } from "@/hooks/cascader";
import { deepClone } from "@/utils/util";
import Converter from "@/views/def/table/components/Converter.vue";
import { ref, reactive, nextTick, onMounted } from "vue";

const props = defineProps({
  title: {
    type: String,
    default: "实体"
  },
  width: {
    type: String,
    default: "60%"
  },
  model: {
    type: Boolean,
    default: true
  }
});
const emits = defineEmits(["confirm"]);

const formRef = ref(null);
const tableRef = ref(null);
const tableFormRef = ref(null);
const converterShow = ref(false);
const converterRef = ref(null);

const initTableType = () => {
  if (state.formData.tableTypeCode) {
    const item = filterTreeNode(cascaderOptions.dataList, state.formData.tableTypeCode, "nodeCode");
    if (item) {
      state.formData.tableTypeId = item.id;
      state.formData.tableTypeCode = item.nodeCode;
      state.formData.tableTypeName = item.text;
    }
  } else {
    state.formData.tableTypeId = cascaderOptions.dataList[0].id;
    state.formData.tableTypeCode = cascaderOptions.dataList[0].nodeCode;
    state.formData.tableTypeName = cascaderOptions.dataList[0].text;
  }
};

const cascaderOptions = reactive<BasicCascaderProps>({
  queryForm: { treeCode: "busentity" },
  props: {
    checkStrictly: true,
    multiple: false,
    emitPath: false,
    label: "text",
    value: "id",
    leaf: "leaf",
    lazy: true
  },
  onLoaded: initTableType,
  queryFunction: querySystemTreeNode
});

const { queryCascaderData } = useCascader(cascaderOptions);

const handleTableTypeChange = () => {
  const item = filterTreeNode(cascaderOptions.dataList, state.formData.tableTypeId, "id");
  if (item) {
    state.formData.tableTypeId = item.id;
    state.formData.tableTypeCode = item.nodeCode;
    state.formData.tableTypeName = item.text;
  }
};

const state = reactive({
  readonly: false,
  operationAdd: false,
  dataSourceOptions: deepClone(dataSourceOptions),
  dataTypeOptions: deepClone(dataTypeOptions),
  renderTypeOptions: deepClone(renderTypeOptions),
  tableForm: {
    total: 0,
    list: deepClone(DefaultColumnList),
    listLoading: false,
    height: getTableHeight(1, true, false) - 75,
    rules: DefColumnRules
  },
  formData: {
    id: "",
    tableShortName: "",
    tableName: "",
    tableKey: "",
    tableComment: "",
    tableTypeId: "",
    tableTypeCode: "1000",
    dataSourceCode: "default",
    tableMode: "1",
    createdTable: false,
    tableTypeName: "",
    dataSourceId: "",
    columns: ""
  },
  formRules: DefTableRules,
  dialogTitle: props.title,
  dialogVisible: false
});

const show = (row, readonly) => {
  if (readonly) {
    state.readonly = readonly;
    state.dialogTitle = `${props.title}详情`;
  } else {
    state.readonly = false;
  }
  if (row && row.id) {
    state.dialogTitle = `修改${props.title}`;
    cloneObject(state.formData, row);
    state.formData.tableShortName = state.formData.tableName.replace("bus_", "");
    queryBusColumnTableData();
  } else {
    state.operationAdd = true;
    state.dialogTitle = `新增${props.title}`;
  }
  initTableType();
  state.dialogVisible = true;
};

const close = () => {
  state.readonly = false;
  state.operationAdd = false;
  state.dialogTitle = props.title;
  state.formData = {
    id: "",
    tableShortName: "",
    tableName: "",
    tableKey: "",
    tableComment: "",
    tableTypeId: "",
    tableTypeCode: "1000",
    dataSourceCode: "default",
    tableMode: "1",
    createdTable: false,
    tableTypeName: "",
    dataSourceId: "",
    columns: ""
  };
  state.tableForm.list = deepClone(DefaultColumnList);
  state.dialogVisible = false;
};

const save = () => {
  formRef.value.validate(async valid => {
    if (valid) {
      tableFormRef.value.validate(async columnValid => {
        if (columnValid) {
          state.formData.tableName = `bus_${state.formData.tableShortName}`;
          state.formData.columns = JSON.stringify(state.tableForm.list);
          let data = { code: 200, msg: "", data: null };
          if (state.operationAdd) {
            data = await addTable(state.formData);
          } else {
            data = await updateTable(state.formData);
          }
          if (data.code === 200) {
            useMessage().success(data.msg);
            emits("confirm", {});
            close();
          } else {
            useMessage().warning(data.msg);
          }
        }
      });
    }
  });
};

const queryBusColumnTableData = async () => {
  state.tableForm.listLoading = true;
  state.tableForm.list = [];
  await queryBusColumnList({
    tableId: state.formData.id,
    ascs: "sn"
  }).then(res => {
    if (res.code === 200) {
      state.tableForm.list = state.tableForm.list.concat(res.data);
    } else {
      state.tableForm.list = deepClone(DefaultColumnList);
      useMessage().warning(res.data.msg);
    }
  });
  state.tableForm.listLoading = false;
};

const handleInputChange = (val, index, columnName) => {
  if (columnName === "dataLength" || columnName === "dataPrecision") {
    state.tableForm.list[index][columnName] = parseInt(val);
  } else if (columnName === "columnName") {
    console.log(val, toCamelCase(val));
    state.tableForm.list[index][columnName] = val;
    state.tableForm.list[index]["columnKey"] = toCamelCase(val);
  } else {
    state.tableForm.list[index][columnName] = val;
  }
};

const handleSelectChange = (val, index, columnName) => {
  state.tableForm.list[index][columnName] = val;
};

const handleTableNameChange = val => {
  const tableKey = toCamelCase(val);
  state.formData.tableName = `bus_${val.toLowerCase()}`;
  state.formData.tableKey = tableKey;
};

const handleAddColumn = () => {
  const newRow = {
    id: "",
    columnName: "",
    columnKey: "",
    columnComment: "",
    dataType: "varchar",
    renderType: "TextInput",
    ctrlConfig: "",
    convertConfig: {},
    dataLength: 32,
    dataPrecision: 0,
    nullable: true,
    primaryKey: false,
    defaultValue: ""
  };
  state.tableForm.list.push(newRow);
};

const handleDeleteColumn = (index: number) => {
  state.tableForm.list.splice(index, 1);
};

const swapArray = (arr: any[], sourceIndex: number, targetIndex: number) => {
  const source = arr[sourceIndex];
  const target = arr[targetIndex];
  arr[sourceIndex] = target;
  arr[targetIndex] = source;
  return arr;
};

const swapUp = (index: number) => {
  state.tableForm.list = swapArray(state.tableForm.list, index, index - 1);
};

const swapDown = (index: number) => {
  state.tableForm.list = swapArray(state.tableForm.list, index, index + 1);
};

const handleConverterAdd = row => {
  console.log(row);
  converterShow.value = true;
  nextTick(() => {
    converterRef.value.show({ columnKey: row.columnKey });
  });
};

const handleConverterRemove = row => {
  const index = state.tableForm.list.findIndex(n => n.columnKey === row.columnKey);
  if (index > -1) {
    state.tableForm.list[index].ctrlConfig = "";
    state.tableForm.list[index].convertConfig = {};
  }
};

const handleConverterConfirm = () => {
  converterRef.value.getFormData().then(converter => {
    const index = state.tableForm.list.findIndex(n => n.columnKey === converter.columnKey);
    if (index > -1) {
      state.tableForm.list[index].ctrlConfig = JSON.stringify(converter);
      state.tableForm.list[index].convertConfig = converter;
    }
    converterShow.value = false;
  });
};

onMounted(() => {
  queryCascaderData();
});

defineExpose({
  show,
  close,
  save
});
</script>

<style lang="scss" scoped>
.form-table {
  .el-form-item {
    margin-bottom: 0px !important;
  }
}
</style>
